﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MVCTutorial.Core.Impls.Repository;

namespace MVCTutorial.Core.Model
{
	public class User
	{
		private IList<Skill> skills;

		public int Id { get; internal set; }
		public string Name { get; set; }
		public IList<Skill> Skills
		{
			get
			{
				if (skills == null)
					skills = RepositoryProvider.SkillRepository.GetForUser(Id).ToList() ?? new List<Skill>();

				return skills;
			}
			set { skills = value; }
		}

		public User(string name)
		{
			Name = name;
		}

		public User(string name, IList<Skill> skills)
		{
			Name = name;
			Skills = skills;
		}

		internal User(int id, string name)
		{
			Id = id;
			Name = name;
		}

		internal User(int id, string name, IList<Skill> skills)
		{
			Id = id;
			Name = name;
			Skills = skills;
		}

		internal void Save()
		{
			IUserRepository userRepo = RepositoryProvider.UserRepository;
			
			if (Id == 0)
				userRepo.Add(this);
			else
				userRepo.Update(this);

			ISkillRepository skillRepo = RepositoryProvider.SkillRepository;

			var oldSkills = skillRepo.GetForUser(Id);
			foreach (var skill in oldSkills)
				skillRepo.DetachFromUser(skill.Id, Id);

			foreach (var skill in Skills)
				skillRepo.AttachToUser(skill.Id, Id);

			Skills = skillRepo.GetForUser(Id).ToList();
		}

		internal static IEnumerable<User> GetAll()
		{
			return RepositoryProvider.UserRepository.GetAll();
		}

		internal static IEnumerable<User> Search(string namelike)
		{
			var users = GetAll();

			if (string.IsNullOrWhiteSpace(namelike))
				return users;

			if (users == null)
				return null;

			return 
				from u in users 
				where u.Name.ToLower().Contains(namelike.ToLower()) 
				select u;
		}

		internal static User GetById(int id)
		{
			return RepositoryProvider.UserRepository.GetById(id);
		}

		internal static void Delete(int id)
		{
			IUserRepository userRepo = RepositoryProvider.UserRepository;
			
			User user = userRepo.GetById(id);

			if (user == null)
				return;

			IEnumerable<Skill> skills = user.Skills;

			userRepo.Remove(user.Id);

			if (skills == null)
				return;

			ISkillRepository skillRepo = RepositoryProvider.SkillRepository;

			foreach (var skill in skills)
				skillRepo.DetachFromUser(skill.Id, user.Id);
		}

		internal void SetSkills(int[] skillIds)
		{
			if (skillIds.Count() < 1)
			{
				Skills.Clear();
				return;
			}

			ISkillRepository skillRepo = RepositoryProvider.SkillRepository;
			var skills = skillRepo.GetAll();
			Skills = skills.Where(s => skillIds.Contains(s.Id)).ToList();
		}
	}
}